package com.cloud.rest;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.*;

import com.cloud.datastore.ScoreboardDatastore;
import com.cloud.rest.api.Action;
import com.cloud.rest.api.ActionFactory;
import com.google.appengine.api.datastore.Entity;

@SuppressWarnings("serial")
public class RestAPIServlet extends HttpServlet {
	
	private static ScoreboardDatastore sd = ScoreboardDatastore.getInstance();
	private static ActionFactory af = ActionFactory.getInstance();
	
	public static final String PARAM_ACTION = "action";
	public static final String PARAM_BUCKET = "bucket";
	public static final String PARAM_TOP = "top";
	public static final String PARAM_TYPE = "type";
	public static final String PARAM_SCORE = "score";
	public static final String PARAM_ID = "id";
	
	public void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws IOException {
		
		String mAction = req.getParameter(PARAM_ACTION);
		Map<String,String[]> paramMap = req.getParameterMap();
		Map<String,String> fstParamMap = new HashMap<String,String>();
		for (String s : paramMap.keySet())
			fstParamMap.put(s, paramMap.get(s)[0]);
		
		doAction(mAction, fstParamMap, resp);
	}
	
	public static final String ACTION_QUERY = "query";
	public static final String ACTION_CREATE = "create";
	public static final String ACTION_INSERT = "insert";
	
	private void doAction(String action, Map<String,String> paramMap, HttpServletResponse resp) {
			if (action.equals(ACTION_QUERY)){
				/*
				 * Query action requires parameters: "bucket", "top"
				 */
				Action a = ActionFactory.getActionByName(action);
				if (a.isParamValid(paramMap.keySet())) {
					String bucket = paramMap.get(PARAM_BUCKET);
					String top = paramMap.get(PARAM_TOP);
					List<Entity> l = ScoreboardDatastore.getTopScoreOfBucket(bucket, Integer.parseInt(top));
					String out = ScoreboardDatastore.getTopScoreStringFromEntityList(l);
					doResponse(resp, out);
				}
				else {
					sendError(resp, a);
				}
			} else if (action.equals(ACTION_CREATE)) {
				/*
				 * Query action requires parameters: "bucket"
				 */
				Action a = ActionFactory.getActionByName(action);
				if (a.isParamValid(paramMap.keySet())) {
					String bucket = paramMap.get(PARAM_BUCKET);
					boolean success = ScoreboardDatastore.createBucket(bucket);
					String out = "success: "+success;
					doResponse(resp, out);
				}
				else {
					sendError(resp, a);
				}
			} else if (action.equals(ACTION_INSERT)) {
				/*
				 * Query action requires parameters: "bucket", "id", "score"
				 */
				Action a = ActionFactory.getActionByName(action);
				if (a.isParamValid(paramMap.keySet())) {
					String bucket = paramMap.get(PARAM_BUCKET);
					String id = paramMap.get(PARAM_ID);
					String score = paramMap.get(PARAM_SCORE);
					boolean success = ScoreboardDatastore.addScoreToBucket(bucket, id, Double.parseDouble(score));
					String out = "success: "+success;
					doResponse(resp, out);
				}
				else {
					sendError(resp, a);
				}
			} else {
				String out = "No such action \""+action+"\". Available action(s): ";
				for (String s : ActionFactory.getActionsMap().keySet())
					out += s+", ";
				doResponse(resp, out);
			}
	}
	
	private void sendError(HttpServletResponse resp, Action a) {
		String errorMsg = "API ERROR: ";
		errorMsg += "action \""+ a.getName() +"\" requires parameters ";
		for ( String s : a.getRequiredParams())
			errorMsg += (s + " ");
		doResponse(resp, errorMsg);
	}
	
	private void doResponse(HttpServletResponse resp, String out) {
		try {
			resp.getWriter().write(out);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
